#ifndef SCENE_H
#define SCENE_H

#include <list>
#include <assert.h>
#include <iostream>

#include "../Ray.h"
#include "../Material.h"
#include "../PointLight.h"
#include "../Color/Color.h"
#include "../Vector/Vector.h"
#include "../Camara/Camara.h"
#include "../Primitives/Primitives.h"

#define VERSOR_X Vector(1,0,0)
#define VERSOR_Y Vector(0,1,0)
#define VERSOR_Z Vector(0,0,1)

using namespace std;

#define DEBUG

class Scene{
	public:

		/* Constructor por defecto */
		Scene();

		/* Setea los atributos de la camara */
		void set_camera(const Camara& c);

		/* mueve la camara */
		void move_camara(const int d, const double l);

		/* Setea el ancho y alto de la pantalla */
		void set_screen(int _w, int _h, double _sample_w, double _sample_h);

		/* Agrega una primitiva a la escena */
		void add_primitive(const Primitive* p);

		/* Agrega una luz a la escena */
		void add_light(PointLight l);

		/* Define la luz de ambiente */
		void set_ambient_light(double al);

		/* define el color de fondo */
		void set_background_color(Color c);

		/* define cuantas recursiones de reflejo se producen */
		void set_recursion_limit(unsigned int l);

		/* define la maxima profundidad */
		void set_max_ray_distance(double d);

		/* devuelve el color de un pixel (x,y) en la pantalla */
		Color pixel(int x, int y);

	private:

		/* Datos de la camara */

			Camara camara;

		/* Datos de la pantalla */

			/* ancho de la pantalla (en pixels) */
			double screen_w;
			/* alto de la pantalla (en pixels) */
			double screen_h;
			/* distancia de la camara al medio de la pantalla */
			//double focal_length;
			/* ancho de cada 'pixel' de la pantalla en el espacio */
			double sample_w;
			/* alto de cada 'pixel' de la pantalla en el espacio */
			double sample_h;
			/* versor que indica la direccion horizontal de la pantalla en el espacio */
			Vector sample_dw;
			/* versor que indica la direccion vertical de la pantalla en el espacio */
			Vector sample_dh;

		/* Lista de primitivas */
		list<const Primitive*> primitives;

		/* Lista de luces */
		list<PointLight> lights;

		double ambient_light;
		Color background;
		unsigned int recursion_limit;
		double max_ray_distance;

		/* Intersects */
		Color traceRay(Ray r, unsigned int recursion_depth, const Primitive* tabu = NULL);

		/* Calcula las componentes en que aporta una luz */
		LightIntensity getLighting(const Primitive* p, const PointLight light, const Vector point, const Vector ray_d, const Vector normal);

};

#endif
